Release 10.1A: OpenEdge Development:
ProDataSets


Accessing Data-Relations

This section looks at attributes and methods that give you access to, and information about, the ProDataSet’s Data-Relations. First, there is a NUM-RELATIONS attribute to return the number of Data-Relations, as shown:

Syntax
[ integer-var = ] dataset-handle:NUM-RELATIONS 

You can retrieve the handle to a particular relation using the GET-RELATION method with its numeric index in the ProDataSet or its name. For example:

Syntax
[ handle-var = ] dataset-handle:GET-RELATION 
   ( relation-index-expr | relation-name-expr) 

Where:

Once you have a relation object, you can access its attributes. CHILD-BUFFER returns the buffer handle of the child member of the Data-Relation:

Syntax
[ buffer-handle = ] relation-handle:CHILD-BUFFER 

Likewise, PARENT-BUFFER returns the parent buffer handle of the relation:

Syntax

[ buffer-handle = ] relation-handle:PARENT-BUFFER

Two attributes and method provide access to a relation through one of the member buffer handles. The NUM-CHILD-RELATIONS attribute returns the number of Data-Relations for which the buffer is the parent. There might be more than one because a buffer can be a parent in multiple relations, with different children, as shown:

Syntax
[ integer-var = ] buffer-handle:NUM-CHILD-RELATIONS 

As with the ProDataSet’s GET-BUFFER-HANDLE method, you can use the GET-CHILD-RELATION method to walk through the list of child relations for a particular parent buffer using the buffer index within the list:

Syntax
[ handle-var = ] buffer-handle:GET-CHILD-RELATION ( integer-expr ) 

You can also point back from the child buffer of a Data-Relation to its PARENT-RELATION:

Syntax
[ handle-var = ] buffer-handle:PARENT-RELATION 

Because a buffer cannot have more than one parent, there is no need for an attribute to return the number of parent buffers.

This code sample and output for DynamicMain2.p confirms the parent and child of the ProDataSet’s one relation:

/* This block shows some of the Data-Relation methods and 
   attributes. */ 
hRelation = hDataSet:GET-RELATION(1). 
MESSAGE "Buffer" hRelation:CHILD-BUFFER:NAME "is the child of" 
        hRelation:PARENT-BUFFER:NAME 
           VIEW-AS ALERT-BOX. 

Progress creates a dynamic query representing each Data-Relation in the ProDataSet. This query provides filtering of child records in each relation so that you can use it if you want to walk the child records for the current parent. If you attach this query to a browse object, the browse is automatically refreshed with the right child records as the currently selected parent record changes. Several attributes provide access to and information about this query.

The first attribute is the relation’s WHERE-STRING, which returns the current where clause used to link the child of the relation to its parent, beginning with the keyword WHERE but not including the FOR EACH phrase of a QUERY-PREPARE method on a query. This attribute evaluates to the query string that Progress generates for you based on the relation between parent and child. You could use this attribute to build an extended query of your own based on the default relationship but extending it in some way:

Syntax
[ character-var = ] relation-handle:WHERE-STRING 

The RELATION-FIELDS attribute returns the list of join fields between the parent and child as specified in the relation definition. This can be useful in code that exploits or extends the list of join fields without parsing the WHERE-STRING. In the default case, it provides essentially the same information but not necessarily in an ideal form for analyzing the relation:

Syntax
[ character-var = ] relation-handle:RELATION-FIELDS 

You can access the dynamic query itself through the relation’s QUERY attribute:

Syntax
[ handle-var = ] relation-handle:QUERY 

This returns the handle of the navigation query that Progress manages to filter children of the current parent when navigating the ProDataSet. This is not the same as the query defined for a Data-Source. This automatically generated query expresses the relation between parent and child temp-tables. This handle cannot be set, and the query cannot be modified. You can use this query to navigate the child records, if you wish. This might be useful because it is automatically opened for you each time the parent changes. Progress can insert the correct parent key field values directly into the child query each time the parent record changes, so it does not need to be fully prepared when the parent changes. This makes this default query more efficient than a 4GL query you would re-prepare and reopen yourself each time the parent changes. You can also prepare and open your own query on any of the member buffers, or use FOR EACH or FIND syntax to access the rows in any member table.

As an example, you can add this MESSAGE statement to the procedure DynamicMain2.p:

MESSAGE "WHERE-STRING: " hRelation:WHERE-STRING SKIP 
        "RELATION-FIELDS: " hRelation:RELATION-FIELDS VIEW-AS ALERT-BOX. 

The code output shows you the WHERE-STRING and RELATION-FIELDS attributes for the ProDataSet’s one relation:

As you can see, the WHERE-STRING of the query selects records in ttOrder whose CustNum matches ttCustomer. The RELATION-FIELDS attribute lists the fields used in the join. You can use either of these strings as a starting point, if you want, for a query of your own. Remember that you cannot change these strings or alter the default query itself. You can only use the strings to construct a new query of your own if you need to refine the selection in some way.

So let’s use this query to walk through the records in the ttOrder table:

hQuery = hRelation:QUERY. 
hQuery:QUERY-OPEN().  
hQuery:GET-FIRST(). 
hBuffer = hRelation:CHILD-BUFFER. 
DO WHILE NOT hQuery:QUERY-OFF-END: 
    MESSAGE hBuffer:BUFFER-FIELD(1):NAME 
            hBuffer:BUFFER-FIELD(1):BUFFER-VALUE SKIP 
            hBuffer:BUFFER-FIELD(2):NAME 
            hBuffer:BUFFER-FIELD(2):BUFFER-VALUE 
        VIEW-AS ALERT-BOX. 
    hQuery:GET-NEXT(). 
END. 

This block of code retrieves the relation’s query, whose join fields and where-clause you’ve already seen. It opens the query, retrieves the first record, and displays the first two fields in the buffer for each record that satisfies the query.

If you run the procedure with this block of code, you get nothing. Why?

The reason is that there’s no ttCustomer record selected. The ProDataSet does not automatically select any records in its temp-tables. You have to set the navigation in motion with queries or find statements of your own. The ProDataSet prepares queries for dependent tables, but again, you need to use the query to actually bring records into the buffers.

If you add this next statement just before the code in the previous code example, it brings the first (and, in this case, only) ttCustomer record into that parent table’s buffer:

hRelation:PARENT-BUFFER:FIND-FIRST(). 

Now the query for ttOrder has a proper ttCustomer.CustNum value for its own query, and you get the results you expect, as shown:

   

There are several other relation attributes. For example:

Syntax
[ logical-var = ] relation-handle:REPOSITION. 

This method returns true if the relation is a REPOSITION relation, otherwise false. It can be set to change the mode of a relation.

The ProDataSet also supports a logical RELATIONS-ACTIVE attribute. By default, all relations in a ProDataSet are active. To deactivate all the Data-Relations in a ProDataSet, set the attribute value to false, as shown:

Syntax
dataset-handle:RELATIONS-ACTIVE = FALSE. 

To reactivate them, set the attribute to TRUE.

Alternatively, you can deactivate or reactivate a relation between two buffers in a ProDataSet by setting the ACTIVE attribute on the relation handle, as shown:

Syntax
relation-handle:ACTIVE = TRUE | FALSE. 

Setting RELATIONS-ACTIVE to false for a ProDataSet is equivalent to setting ACTIVE to false on all Relations individually. Likewise, setting RELATIONS-ACTIVE to true for a ProDataSet sets the ACTIVE attribute to true for each individual relation. The most common use of RELATIONS-ACTIVE happens when you are operating in a mode where a FILL should operate on each buffer using its own individual query, without the nested filling of a parent and its children that usually occurs otherwise. This might be done for efficiency. Setting RELATIONS-ACTIVE to false is easier than traversing the ProDataSet’s relations individually. Likewise, you might want to turn all relations back on after completing a FILL so that they are used to traverse the data after it has been loaded.

When a relation is false, there are several changes to the default behavior of the ProDataSet, depending on whether the FILL is done on the ProDataSet handle or on one of its buffer handles.

First, during a FILL on a ProDataSet temp-table buffer, if Progress encounters a deactivated relation as it traverses the parent-child tree starting at that buffer, it does not fill the child of that relation and does not continue down that branch of the relation tree at all. In other words, a FILL on a ProDataSet buffer fills from that buffer down, stopping at any level that has no children and at any level where the relation to a child is deactivated.

By contrast, if the FILL is done on the ProDataSet handle, then every child of a deactivated relation is treated as a top-level table and filled either according to its query definition, if it has one, or with all records from its Data-Source.

Second, if a relation is inactive during navigation of a ProDataSet, the dynamic query for the child table is not prepared or opened as parent records are selected, even if there is a browse associated with the relation’s query. Any access to the child temp-table must be through a query, FOR EACH, or other standard Progress construct in the application code.

No implicit behavior occurs when a relation is reactivated. There is no automatic synchronization of the hierarchy below the newly active relation. If you want to resync related buffers when you set the ACTIVE attribute to true, you can do this with the SYNCHRONIZE method on the parent buffer. The "Doing a partial ProDataSet FILL to return Order headers" section shows examples of deactivating and activating Data-Relations.

Standard object attributes that are defined for the Data-Relation object include:


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095